﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Mqtt.Callback.Handlers;
using MQTTnet;
using MQTTnet.Client.Publishing;
using MQTTnet.Server;
using MQTTnet.Server.Status;
using Service.Mqtt.Callback;
using Service.Mqtt.Callback.Handlers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Model.Configuration_Model;
using Newtonsoft.Json;
using RSNetDevice.Data;

namespace Service.Mqtt
{
    /// <summary>
    /// mqtt 服务
    /// </summary>
    public partial class MqttServerService
    {
        public void Start()
        {
            _mqttServerStorage.Configure();

            _mqttClientDisconnectedHandler.MqttServer = this;
            _mqttClientConnectedHandler.MqttServer = this;
            //客户端建立连接后，连接的处理程序执行操作
            _mqttServer.ClientConnectedHandler = _mqttClientConnectedHandler;
            //客户端断开连接的处理程序在连接断开时执行操作
            _mqttServer.ClientDisconnectedHandler = _mqttClientDisconnectedHandler;
            //收到客户端订阅
            _mqttServer.ClientSubscribedTopicHandler = _mqttClientSubscribedTopicHandler;
            //客户端取消订阅
            _mqttServer.ClientUnsubscribedTopicHandler = _mqttClientUnsubscribedTopicHandler;
            //收到客户端发布
            _mqttServer.ApplicationMessageReceivedHandler = _messageHandler;

            try
            {
                //异步启动并等待
                _mqttServer.StartAsync(CreateMqttServerOptions()).GetAwaiter().GetResult();
                _logger.LogInformation($"MQTT 服务启动成功 监听 {_mqttServer.Options.DefaultEndpointOptions.Port}");
            }
            catch (Exception ex)
            {
                var message = new StringBuilder(ex.Message);

                var inner = ex.InnerException;
                while (inner != null)
                {
                    message.Append("\nINNER EXCEPTION: ");
                    message.Append(inner.Message);
                    inner = inner.InnerException;
                }

                _logger.LogError(message.ToString());
            }


        }

        public Task<IList<IMqttClientStatus>> GetClientStatusAsync()
        {
            return _mqttServer.GetClientStatusAsync();
        }

        public Task<IList<IMqttSessionStatus>> GetSessionStatusAsync()
        {
            return _mqttServer.GetSessionStatusAsync();
        }

        public Task ClearRetainedApplicationMessagesAsync()
        {
            return _mqttServer.ClearRetainedApplicationMessagesAsync();
        }

        public Task<IList<MqttApplicationMessage>> GetRetainedApplicationMessagesAsync()
        {
            return _mqttServer.GetRetainedApplicationMessagesAsync();
        }
        public async Task<MqttClientPublishResult> Publish(RealTimeData data)
        {
            var applicationMessage = new MqttApplicationMessage()
            {
                Topic = "JH/Data",
                Payload = System.Text.Encoding.Default.GetBytes(JsonConvert.SerializeObject(data))
            };
            if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
            return await _mqttServer.PublishAsync(applicationMessage);
        }
        public async Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage)
        {
            if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
            return await _mqttServer.PublishAsync(applicationMessage);
        }
        /// <summary>
        /// mqtt 服务配置 Options
        /// </summary>
        /// <returns></returns>
        private IMqttServerOptions CreateMqttServerOptions()
        {
            var options = new MqttServerOptionsBuilder()
                //防止多个主题被每个客户端订阅。  订阅拦截
                .WithSubscriptionInterceptor(_mqttServersubscriptioninterceptor)
                //告诉服务器允许每个客户端最大的待处理消息。
                .WithMaxPendingMessagesPerClient(_mqttSettings.MaxPendingMessagesPerClient)
                //告诉服务器使用默认的通信超时。
                .WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(_mqttSettings.CommunicationTimeout))
                //连接验证，验证client id，用户名，密码什么的
                .WithConnectionValidator(_mqttConnectionValidator)
                //告诉服务器使用存储。
                .WithStorage(_mqttServerStorage);

            // Configure unencrypted connections
            if (!_mqttSettings.TcpEndPoint.Enabled)
                options.WithoutDefaultEndpoint();
            //告诉服务器使用默认端点。	
            options.WithDefaultEndpoint();
            if (_mqttSettings.TcpEndPoint.TryReadIPv4(out var address4))
                options.WithDefaultEndpointBoundIPAddress(address4);
            if (_mqttSettings.TcpEndPoint.TryReadIPv6(out var address6))
                options.WithDefaultEndpointBoundIPV6Address(address6);
            //协议里默认是用1883 端口
            options.WithDefaultEndpointPort(_mqttSettings.TcpEndPoint.Port);
            if (_mqttSettings.ConnectionBacklog > 0)
                options.WithConnectionBacklog(_mqttSettings.ConnectionBacklog);
            if (_mqttSettings.EnablePersistentSessions)
                options.WithPersistentSessions();
            if (_mqttSettings.UseOriginalReseiverClientId)
                //发布拦截
                options.WithApplicationMessageInterceptor(_messageInterceptor);
            return options.Build();
        }
    }
    /// <summary>
    /// mqtt 服务
    /// </summary>
    public partial class MqttServerService
    {
        private readonly ILogger<MqttServerService> _logger;
        private readonly MqttServerSubscriptionInterceptor _mqttServersubscriptioninterceptor;
        private readonly IConfiguration _configuration;

        private readonly MqttServerStorage _mqttServerStorage;
        private readonly MqttSettingsModel _mqttSettings;
        private readonly MqttClientConnectedHandler _mqttClientConnectedHandler;
        private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
        private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
        private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
        private readonly MqttServerConnectionValidator _mqttConnectionValidator;
        private readonly MqttApplicationMessageReceivedHandler _messageHandler;

        private readonly MqttApplicationMessageInterceptor _messageInterceptor;
        private readonly IMqttServer _mqttServer;

        public MqttServerService(
             MqttSettingsModel mqttSettings,
            CustomMqttFactory mqttFactory,
            MqttClientConnectedHandler mqttClientConnectedHandler,
            MqttClientDisconnectedHandler mqttClientDisconnectedHandler,
            MqttClientSubscribedTopicHandler mqttClientSubscribedTopicHandler,
            MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
            MqttServerConnectionValidator mqttConnectionValidator,
            MqttApplicationMessageReceivedHandler messageHandler,
            MqttApplicationMessageInterceptor messageInterceptor,
            MqttServerStorage mqttServerStorage,
            ILogger<MqttServerService> logger,
            MqttServerSubscriptionInterceptor mqttServersubscriptioninterceptor,
            IConfiguration configuration

            )
        {
            _mqttSettings = mqttSettings;
            this._mqttClientConnectedHandler = mqttClientConnectedHandler ?? throw new ArgumentNullException(nameof(mqttClientConnectedHandler));
            this._mqttClientDisconnectedHandler = mqttClientDisconnectedHandler ?? throw new ArgumentNullException(nameof(mqttClientDisconnectedHandler));
            this._mqttClientSubscribedTopicHandler = mqttClientSubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientSubscribedTopicHandler));
            this._mqttClientUnsubscribedTopicHandler = mqttClientUnsubscribedTopicHandler ?? throw new ArgumentNullException(nameof(mqttClientUnsubscribedTopicHandler));
            this._messageHandler = messageHandler ?? throw new ArgumentNullException(nameof(messageHandler));
            this._mqttConnectionValidator = mqttConnectionValidator ?? throw new ArgumentNullException(nameof(mqttConnectionValidator));
            this._messageInterceptor = messageInterceptor ?? throw new ArgumentNullException(nameof(messageInterceptor));
            this._mqttServerStorage = mqttServerStorage ?? throw new ArgumentNullException(nameof(mqttServerStorage));
            this._logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _mqttServersubscriptioninterceptor = mqttServersubscriptioninterceptor;
            _configuration = configuration;


            _mqttServer = mqttFactory.CreateMqttServer();
        }


    }
}
